<?php

namespace App\Services\Login;

use App\Constant\Enum;
use App\Libraries\AppSocialite\AppSocialite;
use App\Libraries\AppSocialite\User;
use App\Models\OAuthUser;
use App\Services\User\RegisterUserService;
use App\Services\User\UserUuidService;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Log;
use Tymon\JWTAuth\Facades\JWTAuth;

class OAuth
{
    /**
     * Handle OAuth login request.
     *
     * @param array $attributes
     *
     * @return  array
     */
    public function handle(array $attributes)
    {
        $socialiteUser = $user = AppSocialite::driver($attributes['driver'])->user();
        $oauthUser = $this->oauthUser($attributes['driver'], $user->getId());//对应平台用户

        if (!$oauthUser) {
            if (auth('jwt')->guest()) {
                $loggedUser = $this->register($user);
            } else {
                $loggedUser = auth()->user();
            }

            $oauthUser = $this->linkUser($attributes['driver'], $loggedUser, $user);
        }
        $user = $oauthUser['user'];
        if (!$user) {
            if ($oauthUser) {
                $hasLoggedUser = \App\Models\User::query()->where('openid', $oauthUser['oauth_id'])->first();
                if (!$hasLoggedUser) {
                    /** @var \App\Models\User $loggedUser */
                    $loggedUser = $this->register($socialiteUser);
                    $oauthUser->update([
                        'user_id' => $loggedUser->id
                    ]);
                    $oauthUser->load('user');
                    $user = $oauthUser['user'];
                } else {
                    $user = $hasLoggedUser;
                }
            }
        }
        if ($user) {
            $user->update([
                'last_login_at' => Carbon::now(),
                'last_login_ip' => request()->getClientIp(),
            ]);
        } else {
            Log::debug("OAuth Failed.");
            Log::error($oauthUser);
        }

        return JWTAuth::fromUser($user);
    }

    /**
     * Register.
     *
     * @param \App\Libraries\AppSocialite\User $user
     *
     * @return  \App\Models\User
     */
    protected function register(User $user)
    {
        $pid = request()->get('pid') ?? '';
        $cid = request()->get('cid') ?? '';
        $parentId = 0;
        if (!empty($pid)) {
            $parentId = UserUuidService::decode($pid);
            if (!empty($parentId)) {
                $parentId = \App\Models\User::query()->find($parentId)->id ?? 0;
            }
        }

        return (new RegisterUserService())->register([
            'username' => $user->getId(),
            'password' => '',
            'nickname' => $user->getName(),
            'phone' => '',
            'avatar' => $user->avatar,
            'parent_id' => (int)$parentId,
            'openid' => $user->getId(),
            'cid' => $cid,
            'pid' => $pid,
            'status' => Enum::STATUS_ENABLED,
            'registered_at' => Carbon::now(),
            'last_login_ip' => request()->getClientIp(),
            'last_login_at' => Carbon::now(),
        ]);
    }

    /**
     * Link user.
     *
     * @param string $driver
     * @param \App\Models\User $loggedUser
     * @param \App\Libraries\AppSocialite\User $user
     *
     * @return  \App\Models\OAuthUser
     */
    protected function linkUser($driver, $loggedUser, $user)
    {
        return (new OAuthUser())->register(
            $loggedUser['id'] ?? (optional($loggedUser)->id ?? 0),
            $driver,
            $user->getId(),
            $user->getName(),
            $user->email ?? '',
            $user->avatar ?? '',
            $user->unionid ?? ''
        );
    }

    /**
     * OAuth user.
     *
     * @param string $driver
     * @param string $id
     *
     * @return  \App\Models\OAuthUser|null
     */
    protected function oauthUser($driver, $id)
    {
        return OAuthUser::ofProvider($driver)->ofOAuthId($id)->first();
    }
}
